simple functional queue from Okasaki#558
Conversation
b7c4a9c to
a3c0424
Compare
b22b379 to
5fb8647
Compare
|
this is ready for re-review |
| class Op α o where | ||
| applyOp : α → o → TimeM ℕ α |
There was a problem hiding this comment.
This has no docstring; and this only makse sense if you are saying "for any given pair of types α o, there is exactly one possible operation".
There was a problem hiding this comment.
how else should I write this? no typeclass at all?
There was a problem hiding this comment.
Yes, I think drop the typeclass entirely.
| /-- Enqueue an element. -/ | ||
| def push {α : Type u} (x : α) (q : FunctionalQueue α) | ||
| : TimeM ℕ (FunctionalQueue α) := do | ||
| TimeM.tick 1 | ||
| rebalance ⟨ q.front, x :: q.back ⟩ |
There was a problem hiding this comment.
In my opinion, the TimeM stuff clutters the API here; especially if you find yourself wanting to execute this code, and now end up computing a bunch of counters that you have no interest in. I'd suggest something like
| /-- Enqueue an element. -/ | |
| def push {α : Type u} (x : α) (q : FunctionalQueue α) | |
| : TimeM ℕ (FunctionalQueue α) := do | |
| TimeM.tick 1 | |
| rebalance ⟨ q.front, x :: q.back ⟩ | |
| /-- Enqueue an element. -/ | |
| def push {α : Type u} (x : α) (q : FunctionalQueue α) : FunctionalQueue α := | |
| rebalance ⟨q.front, x :: q.back⟩ | |
| /-- Push as an algorithm | |
| def pushAlg {α : Type u} (x : α) (q : FunctionalQueue α) | |
| : TimeM ℕ (FunctionalQueue α) := do | |
| TimeM.tick 1 | |
| rebalanceAlg ⟨ q.front, x :: q.back ⟩ | |
| @[simp] theorem run_pushAlg : (pushAlg x q).ret = pushAlg x q := sorry |
and similar for the others.
Perhaps this needs discussion on Zulip.
cc292d6 to
36ccb27
Compare
| back : List α | ||
|
|
||
| /-- Well-formedness: if front is empty, back must be empty too. -/ | ||
| def invariant {α : Type u} (q : Raw.FunctionalQueue α) : Prop := |
There was a problem hiding this comment.
| def invariant {α : Type u} (q : Raw.FunctionalQueue α) : Prop := | |
| def Invariant {α : Type u} (q : Raw.FunctionalQueue α) : Prop := |
since this is a Prop
| TimeM.tick 1 | ||
| rebalance ⟨ q.front, x :: q.back ⟩ | ||
|
|
||
| theorem pushInvariant {α : Type u} (x : α) (q : FunctionalQueue α) |
There was a problem hiding this comment.
This should be called Invariant.push
| /-- Physicist method: a potential (lower bound on savings) defined on a | ||
| data structure. | ||
| [Okasaki, *Purely Functional Data Structures*, 1996][okasaki1996] -/ | ||
| class Potential (φ α : Type*) [CommRing φ] [LinearOrder φ] [IsStrictOrderedRing φ] where |
There was a problem hiding this comment.
Note that you can change this to
| class Potential (φ α : Type*) [CommRing φ] [LinearOrder φ] [IsStrictOrderedRing φ] where | |
| class Potential (φ α : Type*) where |
Hi, this is my first attempt at contributing Lean code.
I dug out the old Okasaki, and started off with the simple queue. This should
contain a correctness proof, a complexity proof, and a mapping to a ghost list
of elements.
TimeMdoesn't seem to be enough for amortized complexity soI added a module for that, and I also removed the
ZeroAddtypeclass constraintbecause
\Ndoesn't implement it(!).AI disclosure: all code is mine, but I had some assistance from GLM 5.1 to
tidy up proof terms and get unstuck.